package com.xiaoshuidi.cloud.module.rooms.service.impl;

import cn.hutool.core.convert.NumberChineseFormatter;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.PageParam;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.oss.core.OosFileService;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.reservation.vo.RoomReceiptRespVO;
import com.xiaoshuidi.cloud.module.rooms.controller.app.reserve.vo.ReceiptPageRespVO;
import com.xiaoshuidi.cloud.module.rooms.convert.reservation.ReservationConvert;
import com.xiaoshuidi.cloud.module.rooms.mapper.RoomReceiptMapper;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouseReserve;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomReceipt;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomHouseReserveRepository;
import com.xiaoshuidi.cloud.module.rooms.service.RoomReceiptService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
@RefreshScope
public class RoomReceiptServiceImpl implements RoomReceiptService {

    @Resource
    private RoomHouseReserveRepository roomHouseReserveRepository;
    @Resource
    private RoomReceiptMapper roomReceiptMapper;

    @Value("${receipt.template.path-url}")
    private String TEMPLATE_PATH;

    @Resource
    private OosFileService oosFileService;
    /**
     * 作废收据
     *
     * @param orderId 账单id
     */
    @Override
    public void cancel(Long orderId) {
        //先判断是否支付
        RoomHouseReserve houseReserve = roomHouseReserveRepository.getById(orderId);
        if (houseReserve.getPaymentStatus().equals("1")){
            throw new ServiceException(500,"门店完成收据配置且收款完成后才能进行取消收据操作！");
        }
        RoomReceipt financeReceiptDO = roomReceiptMapper.selectOne(RoomReceipt::getOrderId, orderId);
        if (financeReceiptDO == null){
            throw new ServiceException(500,"付款时未开启收据配置，无收据信息！");
        }
        LambdaUpdateWrapper<RoomReceipt> uw = new LambdaUpdateWrapper<>();
        uw.eq(RoomReceipt::getOrderId,orderId)
                .set(RoomReceipt::getIsCancel , 1);
        roomReceiptMapper.update(null,uw);
    }

    /**
     * 返回发票下载数据
     *
     * @param orderId 账单id
     * @return
     */
    @Override
    public RoomReceiptRespVO down(Long orderId) {
        //先判断是否支付
        RoomHouseReserve houseReserve = roomHouseReserveRepository.getById(orderId);
        if (houseReserve.getPaymentStatus().equals("1")){
            throw new ServiceException(500,"门店完成收据配置且收款完成后才能进行下载收据操作！");
        }
        RoomReceipt financeReceiptDO = roomReceiptMapper.selectOne(RoomReceipt::getOrderId, orderId);
        if (financeReceiptDO == null){
            throw new ServiceException(500,"付款时未开启收据配置，无收据信息！");
        }
        LocalDate invoicingDate = financeReceiptDO.getInvoicingDate();
        RoomReceiptRespVO roomReceiptRespVO = ReservationConvert.INSTANCE.convert2(financeReceiptDO);
        //年月日拆分返回
        roomReceiptRespVO.setYear(invoicingDate.getYear());
        roomReceiptRespVO.setMonth(invoicingDate.getMonthValue());
        roomReceiptRespVO.setDay(invoicingDate.getDayOfMonth());
        return roomReceiptRespVO;
    }

    /**
     * 根据收据id查询收据
     *
     * @param id 收据id
     * @return
     */
    @Override
    public RoomReceiptRespVO get(Long id) {
        RoomReceipt roomReceipt = roomReceiptMapper.selectById(id);
        return ReservationConvert.INSTANCE.convert2(roomReceipt);
    }

    @Override
    public PageResult<ReceiptPageRespVO> page(Integer pageNum, Integer pageSize) {
        log.info("获取当前登录的租客id：{}",SecurityFrameworkUtils.getLoginUser().getId());
        Long userId = Objects.requireNonNull(SecurityFrameworkUtils.getLoginUser()).getId();
        PageParam pageParam = new PageParam();
        pageParam.setPageNo(pageNum);
        pageParam.setPageSize(pageSize);
        LambdaQueryWrapper<RoomReceipt> qw = new LambdaQueryWrapper<>();
        qw.eq(RoomReceipt::getBookerId,userId)
                .orderByDesc(RoomReceipt::getCreateTime);
        PageResult<RoomReceipt> roomReceiptPageResult = roomReceiptMapper.selectPage(pageParam, qw);
        return ReservationConvert.INSTANCE.convert3(roomReceiptPageResult);
    }

    @Override
    public String downPdf(Long id) {
        //获取填充信息
        RoomReceipt roomReceipt = roomReceiptMapper.selectById(id);
        //如果有pdf附件就直接返回
        if (StringUtils.isNotBlank(roomReceipt.getPdfUrl())){
            return roomReceipt.getPdfUrl();
        }
        // 没有则生成收据pdf并更新数据
        String url = generateReceiptPdf(roomReceipt);
        if (StringUtils.isNotBlank(url)){
            roomReceipt.setPdfUrl(url);
            roomReceiptMapper.updateById(roomReceipt);
            return url;
        }else {
            throw new ServiceException(500,"生成收据异常");
        }
    }

    @Override
    public String generateReceiptPdf(RoomReceipt roomReceipt){
        //查询房源名称
        String roomNameAll = roomReceiptMapper.getRoomNameAll(roomReceipt.getOrderId());

        //没有就先生成附件的url
        LocalDate invoicingDate = roomReceipt.getInvoicingDate();
        Map<String,String> map = new HashMap<>();
        map.put("year", String.valueOf(invoicingDate.getYear()));
        map.put("month", String.valueOf(invoicingDate.getMonthValue()));
        map.put("day", String.valueOf(invoicingDate.getDayOfMonth()));
        map.put("number", Objects.nonNull(roomReceipt.getId())?roomReceipt.getId().toString():"");
        map.put("customerName", roomReceipt.getCustomerName());
        map.put("idcard", roomReceipt.getCustomerIdCard());
        map.put("roomNameStr", roomNameAll + " 定金");
        map.put("amount", Objects.nonNull(roomReceipt.getAmount())?roomReceipt.getAmount().toString():"");
        map.put("amountUpper", NumberChineseFormatter.format(roomReceipt.getAmount().doubleValue(),true,true));
        map.put("payMethod", roomReceipt.getPayMethod());
        map.put("drawer", roomReceipt.getDrawerName());
        map.put("payee", roomReceipt.getPayeeName());
        Map<String,Object> map2 = new HashMap<>();
        map2.put("stampImage",roomReceipt.getFinancialSealUrl());
        Map<String,Object> o=new HashMap<>();
        o.put("dataMap",map);
        o.put("imageMap",map2);
        return pdfOut(o);
    }

    private String pdfOut(Map<String,Object> sourceMap) {
        PdfReader reader;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        try {
            // 创建临时文件
            Path tempFilePath = Files.createTempFile("tempPdf"+ IdUtil.fastSimpleUUID(), ".pdf");
            try (FileOutputStream out = new FileOutputStream(tempFilePath.toFile())){
                reader = new PdfReader(TEMPLATE_PATH);// 读取pdf模板
                bos = new ByteArrayOutputStream();
                stamper = new PdfStamper(reader, bos);
                AcroFields form = stamper.getAcroFields();
                //文字类的内容处理
                Map<String, String> dataMap = (Map<String, String>) sourceMap.get("dataMap");
                BaseFont baseFont = BaseFont.createFont();
                form.addSubstitutionFont(baseFont);
                for (String key : dataMap.keySet()) {
                    String value = dataMap.get(key);
                    form.setField(key, value);
                }
                form.setGenerateAppearances(true);
                //图片类的内容处理
                Map<String, Object> imageMap = (Map<String, Object>) sourceMap.get("imageMap");
                for (String key : imageMap.keySet()) {
                    String imgpath = imageMap.get(key).toString();
                    int pageNo = form.getFieldPositions(key).get(0).page;
                    Rectangle signRect = form.getFieldPositions(key).get(0).position;
                    float x = signRect.getLeft();
                    float y = signRect.getBottom();
                    //根据路径读取图片
                    Image image = Image.getInstance(imgpath);
                    //获取图片页面
                    PdfContentByte under = stamper.getOverContent(pageNo);
                    //图片大小自适应
                    image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                    //添加图片
                    image.setAbsolutePosition(x, y);
                    under.addImage(image);
                }
                stamper.setFormFlattening(true);// 如果为false，生成的PDF文件可以编辑，如果为true，生成的PDF文件不可以编辑
                stamper.close();
                Document doc = new Document();
                PdfCopy copy = new PdfCopy(doc, out);
                doc.open();
                PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
                copy.addPage(importPage);
                doc.close();
            } catch (IOException | DocumentException e) {
                System.out.println(e);
            }
            //上传到oos返回url
            String url = oosFileService.oosUploadFile(tempFilePath.toFile());
            //删除临时文件
            tempFilePath.toFile().deleteOnExit();
            return url;
        }catch (IOException e) {
            log.error("生成预定金收据异常，异常信息：", e);
        }
        return null;
    }

}
